﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;
using VisualStock.Infrastructure;
using VisualStock.Infrastructure.Converters;
using VisualStock.Infrastructure.Interfaces;
using VisualStock.Infrastructure.Models;

namespace VisualStock.Modules.StockMarket.Services
{
    /// <summary>
    /// The service which offers the methods to download, import and manage historical data collection
    /// </summary>
    public partial class HistoricalDataService : IHistoricalDataService
    {
        private Dictionary<string, StockHistoricalDataCollection> _historicalDataList = new Dictionary<string, StockHistoricalDataCollection>();

        private IEventAggregator EventAggregator { get; set; }

        public HistoricalDataService(IEventAggregator eventAggregator)
        {
            EventAggregator = eventAggregator;
            this.EventAggregator.GetEvent<CacheAnalysisDataEvent>().Subscribe(CacheAnalysisData, ThreadOption.BackgroundThread);
            this.EventAggregator.GetEvent<SymbolRemovedEvent>().Subscribe(RemoveCachedData, ThreadOption.UIThread);
        }

        public void CacheAnalysisData(KeyValuePair<string, StockHistoricalDataCollection> newData)
        {
            if (!_historicalDataList.ContainsKey(newData.Key))
            {
                _historicalDataList.Add(newData.Key, newData.Value);
                EventAggregator.GetEvent<NewAnalysisDataCachedEvent>().Publish(newData.Key);
            }
        }

        public void RemoveCachedData(List<string> tagetSymbols)
        {
            foreach (string key in tagetSymbols)
                _historicalDataList.Remove(key);
        }

        /// <summary>
        /// Publish the event when a new historical data has been added to the _historicalDataList
        /// </summary>
        /// <param name="targetSymbol">The symbol of the new obtained historical data</param>
        private void OnNewHistoricalDataObtained(string targetSymbol)
        {
            EventAggregator.GetEvent<NewHistoricalDataObtainedEvent>().Publish(targetSymbol);
        }

        #region IHistoricalDataService
        /// <summary>
        /// Try to get the historical data with the specified symbol
        /// </summary>
        /// <param name="symbol">The symbol of the historical data to get</param>
        /// <param name="items">If the historical data is found in the memory cache, this method will return the value</param>
        /// <returns></returns>
        public bool TryGetHistoricalData(string targetSymbol, out StockHistoricalDataCollection items)
        {
            return _historicalDataList.TryGetValue(targetSymbol, out items);
        }

        /// <summary>
        /// Get the information of the historical data of the specific symbol
        /// </summary>
        /// <param name="targetSymbol"></param>
        /// <returns>A Dictionary object which includes the information of the data</returns>
        public StockDataInfomation GetHistoricalDataInfo(string targetSymbol)
        {
            StockDataInfomation dataInfo = new StockDataInfomation();
            dataInfo.StartDate = _historicalDataList[targetSymbol].StartDate;
            dataInfo.EndDate = _historicalDataList[targetSymbol].EndDate;
            dataInfo.TechnicalIndicatorNames = (from item in _historicalDataList
                                                where item.Key.Contains(targetSymbol + "_")
                                                select item.Key).ToList<string>();
            return dataInfo;
        }

        public StockHistoricalDataCollection GetHisroricalData(string targetSymbol, DateTime startDate, DateTime endDate)
        {
            if (startDate.CompareTo(endDate) < 0 &&
                (startDate.CompareTo(_historicalDataList[targetSymbol].EndDate) < 0 || endDate.CompareTo(_historicalDataList[targetSymbol].EndDate) > 0))
            {
                IEnumerable<StockHistoricalDataItem> data = from item in _historicalDataList[targetSymbol]
                                                            where item.QuoteDate.CompareTo(startDate) >= 0 && item.QuoteDate.CompareTo(endDate) <= 0
                                                            select item;
                return new StockHistoricalDataCollection(data);
            }
            return new StockHistoricalDataCollection();
        }

        public bool HasHistoricalData(string targetSymbol)
        {
            if (String.IsNullOrEmpty(targetSymbol)) return false;
            return _historicalDataList.ContainsKey(targetSymbol);
        }

        public void ImportStockHistoricalData(string targetSymbol)
        {
#if SILVERLIGHT
            OpenFileDialog ofd = new OpenFileDialog();
#else
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
#endif
            ofd.Filter = "CSV Files (*.csv)|*.csv";
            if (ofd.ShowDialog().GetValueOrDefault(false))
            {
#if SILVERLIGHT
                _historicalDataList.Add(targetSymbol, HistoricalDataConverter.ConvertFromCSV(ofd.File.OpenRead()));
#else
                _historicalDataList.Add(targetSymbol, HistoricalDataConverter.ConvertFromCSV(ofd.OpenFile()));
#endif
                OnNewHistoricalDataObtained(targetSymbol);
            }
        }

        #endregion
    }
}
